package com.xinsoft.jobs;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.ErpRealTimeDto;
import com.xinsoft.entity.dto.ErpRealTimePageParam;
import com.xinsoft.entity.dto.SysNoticeDTO;
import com.xinsoft.entity.dto.SysNoticeSetDTO;
import com.xinsoft.entity.po.*;
import com.xinsoft.entity.vo.SysNoticeUserVo;
import com.xinsoft.service.*;
import com.xinsoft.service.impl.SyncPullBillAdapter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 物料低库存提醒
 */
@Slf4j
@EnableScheduling
@Component
public class MaterialStockNoticeJob {

    @Autowired
    private ScmStockService stockService;
    @Autowired
    private SysNoticeSetService sysNoticeSetService;
    @Autowired
    private SysNoticeService sysNoticeService;
    @Autowired
    private SysMaterialService sysMaterialService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysActionService actionService;
    @Resource(name = "syncPullBillAdapter")
    private SyncPullBillAdapter syncPullBillAdapter;

    /**
     * 每天10点钟检查一次
     */
    @Scheduled(cron = "0 0 05 * * ?")
    // @Scheduled(cron = "0 0/1 * * * ?")
    public void timeoutReminder() {
        log.info("=========================物料低库存提醒定时任务开始=========================");
        StringBuilder content = new StringBuilder();
        List<SysMaterial> materialDOS = sysMaterialService.list(new LambdaQueryWrapper<SysMaterial>().isNotNull(SysMaterial::getMinStockNum));
        List<Integer> materialIds = materialDOS.stream().map(SysMaterial::getId).collect(Collectors.toList());
        List<List<SysMaterial>> materialIdsPartition = Lists.partition(materialDOS,100);
        ErpRealTimePageParam realTimePageParam = new ErpRealTimePageParam();
        materialIdsPartition.forEach(item -> {
            realTimePageParam.setMaterialIds("(" + StringUtils.join(materialIds, ",") + ")");
            IPage<ErpRealTimeDto> realTimeDtoIPage = syncPullBillAdapter.realtimeInventory(realTimePageParam);
            List<ErpRealTimeDto> realTimeDtos = realTimeDtoIPage.getRecords();
            Map<Integer, List<ErpRealTimeDto>> realTimeDtosGroup = realTimeDtos.stream().collect(Collectors.groupingBy(ErpRealTimeDto::getMaterialId));
            List<String> insufficientMaterialDOS  = item.stream().filter(ma -> {
                if (!realTimeDtosGroup.containsKey(ma.getId()) ||
                        ma.getMinStockNum().compareTo(realTimeDtosGroup.get(ma.getId()).stream().map(item2 -> new BigDecimal(item2.getNum().toString()))
                                .reduce(BigDecimal::add).orElse(BigDecimal.ZERO)) > 0) {
                    return true;
                }
                return false;
            }).map(SysMaterial::getMaterialName).collect(Collectors.toList());
            content.append(StringUtils.join(insufficientMaterialDOS,","));
        });
        String contentString = content.toString();
        if (StringUtils.isNotBlank(contentString)){
            sendContent(contentString);
        }
        log.info("=========================物料低库存提醒定时任务结束=========================");
    }

    /**
     * 发送消息
     */
    public void sendContent(String content) {
        List<SysNoticeSetDTO> sysNoticeSetDTOList = sysNoticeSetService.getSysNoticeSetByActionId(Const.ACTION.MATERIAL_STOCK);
        SysNoticeSetDTO noticeSetDTO = sysNoticeSetDTOList.get(0);
        List<SysNoticeUserVo> sysNoticeUserList = noticeSetDTO.getSysNoticeUserList();
        if (ObjectUtil.isEmpty(sysNoticeUserList)) return ;

        List<Integer> receiveIds = new ArrayList<>();
        List<Integer> deptIds = new ArrayList<>();
        sysNoticeUserList.forEach(item ->{
            if (Objects.equals(item.getDepOrUser(), Const.NOTICE_DEPT)) {
                deptIds.add(item.getDepId());
            }
            if (Objects.equals(item.getDepOrUser(), Const.NOTICE_USER)) {
                receiveIds.add(item.getUserId());
            }
        });
        // 设置接收人
        if (CollectionUtil.isNotEmpty(deptIds)) {
            List<SysUser> userList = sysUserService.list(Wrappers.lambdaQuery(SysUser.class)
                    .eq(SysUser::getStatus, Const.USER_STATUS_NORMAL)
                    .in(SysUser::getDeptId, deptIds));
            if (CollectionUtil.isNotEmpty(userList)) {
                List<Integer> userIdsOfDept = userList.stream().map(SysUser::getId).collect(Collectors.toList());
                receiveIds.addAll(userIdsOfDept);
            }
        }
        if (ObjectUtil.isEmpty(receiveIds)) return ;
        SysNoticeDTO noticeDTO = new SysNoticeDTO();
        SysAction sysAction = actionService.getById(Const.ACTION.MATERIAL_STOCK);
        noticeDTO.setFromUserId(1);   // 管理员发送
        noticeDTO.setContent("如下物料库存过低：" + content);
        noticeDTO.setReceiveIds(receiveIds);
        noticeDTO.setTitle(sysAction.getActionName());
        noticeDTO.setContentUrlParam(noticeSetDTO.getHrefUrl());
        sysNoticeService.send(noticeDTO);
        return ;
    }
}
